package com.xxx.nio.aio;

import com.xxx.nio.utils.ByteBufferUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 文件AIO
 */
@Slf4j
public class FileAio {

    public static void main(String[] args) throws IOException {
        try ( AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ)){
            final ByteBuffer buffer = ByteBuffer.allocate(16);
            log.debug("read begin ..........................................");

            /**
             * 参数1：ByteBuffer
             * 参数2：起始位置
             * 参数3：附件，一个读不完 需要另一个 byteBuffer
             * 参数4：包含两个回调方法 的 回调对象CompletionHandler ，回调 接收结果的操作，当然这两个回调方法 一定是 另一个线程操作的
             */
            channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                /**
                 *  一次 read成功了的 回调方法
                 * @param result       读到的 实际字节数
                 * @param attachment   传过来的 buffer对象
                 */
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    log.debug("read completed. result: {}",  result);
                    attachment.flip();
                    ByteBufferUtil.debugAll(attachment);
                }

                @Override // read 过程中 异常了，将调用
                public void failed(Throwable exc, ByteBuffer attachment) {
                    exc.printStackTrace();
                }
            });

            log.debug("read end ..........................................");
        }catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("主线程 做其他事 ...");
        System.in.read();   // 默认文件 AIO 使用的线程都是守护线程，所以最后要执行 `System.in.read()` 以避免守护线程意外结束
    }

}
